home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CUCD / Programming / OUI / eroll.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  16.1 KB  |  538 lines

  1. // $Id: eroll.cc 1.3 1997/09/17 08:15:27 dlorre Exp $
  2. #include <graphics/gfxmacros.h>
  3. #include <intuition/classes.h>
  4. #include <intuition/classusr.h>
  5. #include <intuition/gadgetclass.h>
  6. #include <intuition/cghooks.h>
  7. #include <intuition/icclass.h>
  8. #include <utility/tagitem.h>
  9. #include <utility/hooks.h>
  10. #include <libraries/gadtools.h>
  11.  
  12. #include <stdio.h>
  13. #include <mydebug.h>
  14. #include <string.h>
  15. #include <math.h>
  16. #if defined( __SASC__ )
  17. #ifdef _IEEE
  18. #include <mieeedoub.h>
  19. #endif
  20. #ifdef _M68881
  21. #include <m68881.h>
  22. #endif
  23. #endif
  24.  
  25. #include "gadgets/eroll.h"
  26. #include "gadgets/eclass.h"
  27. #include "gadgetlist.h"
  28. #include "window.h"
  29. #include "screen.h"
  30.  
  31. #include <proto/dos.h>
  32. #include <proto/graphics.h>
  33. #include <proto/intuition.h>
  34. #include <proto/utility.h>
  35. #include <clib/alib_protos.h>
  36. #include <compiler.h>
  37.  
  38. static Class *BOOPSIeroll ;
  39. static int InitERoll(void) ;
  40. static void FreeERoll(void) ;
  41.  
  42. #if !defined( PI )
  43. #define PI  3.14159265358979323846
  44. #endif
  45.  
  46. const double cPID4  = PI / 4.0  ;
  47. const double cPID2  = PI / 2.0  ;
  48. const double c3PID2  = 3.0 * PI / 2.0 ;
  49. const double c5PID4  = 5.0 * PI / 4.0 ;
  50. const double c7PID4  = 7.0 * PI / 4.0 ;
  51. const double c2PI   = 2.0 * PI ;
  52.  
  53. extern "C" STDARGS ULONG HookEntry() ;
  54.  
  55. // ========================================================================
  56. // ============================  EROLL CLASS =============================
  57. // ========================================================================
  58.  
  59.  
  60. eroll::eroll(gadgetlist *gl,
  61.                void (window::*func)(gadget *, unsigned long, unsigned short),
  62.                long min,
  63.                long max,
  64.                long level,
  65.                BOOL full) : gadget(gl, func),
  66.                             cursel(level), rmin(min), rmax(max), rfull(full)
  67. {
  68.  
  69.     InitERoll() ;
  70.  
  71.     gad = gl->gad  = (Gadget *)NewObject(BOOPSIeroll, NULL,
  72.  
  73.             GA_ID,              gl->ng->ng_GadgetID,
  74.             GA_Top,             gl->ng->ng_TopEdge,
  75.             GA_Left,            gl->ng->ng_LeftEdge,
  76.             GA_Width,           gl->ng->ng_Width,
  77.             GA_Height,          gl->ng->ng_Height,
  78.  
  79.             GA_Previous,        gl->gad,
  80.  
  81.             GA_Immediate,       TRUE,
  82.             GA_FollowMouse,     TRUE,
  83.             GA_RelVerify,       TRUE,
  84.  
  85.             GA_UserData,        EGA_Level,
  86.  
  87.             ICA_TARGET,         ICTARGET_IDCMP,
  88.  
  89.             EGA_Min,             min,
  90.             EGA_Max,             max,
  91.             EGA_Level,           level,
  92.             EGA_Full,            full,
  93.             EGA_XPens,           gl->win->ws->xpens,
  94.  
  95.             TAG_DONE);
  96. }
  97.  
  98. eroll::~eroll()
  99. {
  100.     DisposeObject(gad) ;
  101.     FreeERoll() ;
  102. }
  103.  
  104. void eroll::set(long level, long min, long max, short disable)
  105. {
  106.     SetGadgetAttrs(gad, w, NULL,
  107.         (level != -1)?EGA_Level:TAG_IGNORE,  level,
  108.         (min != -1)?EGA_Min:TAG_IGNORE,      min,
  109.         (max != -1)?EGA_Max:TAG_IGNORE,      max,
  110.         GA_Disabled,                        disable,
  111.         TAG_END) ;
  112. }
  113.  
  114. void eroll::action(unsigned long classe, unsigned short code)
  115. {
  116.     cursel = code ;
  117.     gadget::action(classe, code) ;
  118. }
  119.  
  120. void eroll::keystroke(BOOL shifted)
  121. {
  122.     if (shifted) {
  123.         cursel-- ;
  124.         if (cursel < rmin)
  125.             cursel = rfull?rmax:rmin ;
  126.     }
  127.     else {
  128.         cursel++ ;
  129.         if (cursel > rmax)
  130.             cursel = rfull?rmin:rmax ;
  131.     }
  132.     set(cursel) ;
  133.     gadget::action(NULL, cursel) ;
  134. }
  135.  
  136.  
  137. // ========================================================================
  138. // =============================== EROLL =================================
  139. // ========================================================================
  140.  
  141. struct RollINST {
  142.     BOOL        Full ;                  // Full display : 360° angle
  143.     BOOL        KnobHit ;
  144.     BOOL        RedrawAll ;
  145.  
  146.     WORD        Direction ;
  147.     long        GLeft ;                 // Coordonnées du gadget
  148.     long        GTop ;
  149.     long        GWidth ;
  150.     long        GHeight ;               // Coordonnées du gadget
  151.     long        XRadius, YRadius ;      // Rayons
  152.     long        CLeft, CTop ;           // Coordonnées du centre
  153.     long        CWidth, CHeight ;
  154.     long        KLeft, KTop ;           // Coordonnées du curseur
  155.     long        KRight, KBottom ;
  156.     long        KCenterX, KCenterY ;
  157.     double       KStart ;
  158.     long        XStartPos, YStartPos ;
  159.     long        Total, Top ;
  160.     long        Min, Max, Level ;
  161.     long        DTop, PTop ;
  162.     long        XUnity, YUnity ;
  163.     double      angPhase ;
  164.     double      angWidth ;
  165.     double      angMin ;
  166.     double      Ratio ;
  167.     UWORD       *XPens ;
  168. } ;
  169.  
  170. static ULONG STDARGS dispatchERoll(Class *cl, Object *o, Msg msg);
  171.  
  172. static void     NotifyRoll(Class *, Object *, ULONG, long, gpInput *) ;
  173.  
  174. static ULONG    RenderERoll(Class *, Gadget *, gpRender *) ;
  175.  
  176. static void     RollSize(RollINST *inst, Gadget *g) ;
  177. static void     RollLims(RollINST *inst) ;
  178.  
  179. static unsigned short ditherData[2] = {0x5555,0xAAAA};
  180. static int ERollCnt = 0 ;
  181. int InitERoll(void)
  182. {
  183.     if (ERollCnt) {
  184.         ERollCnt++ ;
  185.     }
  186.     else if (!(BOOPSIeroll = MakeClass(NULL, (UBYTE *)"propgclass", NULL,
  187.         sizeof(RollINST), 0))) {
  188.         ERollCnt = 0 ;
  189.     }
  190.     else {
  191.         BOOPSIeroll->cl_Dispatcher.h_Entry = (HOOKFUNC)HookEntry ;
  192.         BOOPSIeroll->cl_Dispatcher.h_SubEntry = (HOOKFUNC)dispatchERoll;
  193.         BOOPSIeroll->cl_Dispatcher.h_Data = NULL ;
  194.         ERollCnt = 1 ;
  195.     }
  196.     return ERollCnt ;
  197. }
  198.  
  199. void FreeERoll(void)
  200. {
  201.     ERollCnt-- ;
  202.     if (!ERollCnt)
  203.         FreeClass(BOOPSIeroll) ;
  204. }
  205.  
  206. ULONG SAVEDS STDARGS dispatchERoll(Class *cl, Object *o, Msg msg)
  207. {
  208. RollINST *inst ;
  209. ULONG retval = FALSE ;
  210. Object *object ;
  211.  
  212.     GETA4 ;
  213.     switch (msg->MethodID) {
  214.     case OM_NEW:
  215.         if (object = (Object *)DoSuperMethodA(cl, o, msg)) {
  216.             inst = (RollINST *)INST_DATA(cl, object) ;
  217.             inst->KnobHit = FALSE ;
  218.             inst->Min = (long)GetTagData(EGA_Min, 1, ((opSet *)msg)->ops_AttrList) ;
  219.             inst->Max = (long)GetTagData(EGA_Max, 16, ((opSet *)msg)->ops_AttrList) ;
  220.             inst->Full = (long)GetTagData(EGA_Full, FALSE, ((opSet *)msg)->ops_AttrList) ;
  221.             inst->Level = (long)GetTagData(EGA_Level, 1, ((opSet *)msg)->ops_AttrList) ;
  222.             inst->XPens = (UWORD *)GetTagData(EGA_XPens, NULL, ((opSet *)msg)->ops_AttrList) ;
  223.             inst->Total = inst->Max - inst->Min + 1 ;
  224.             inst->Top = inst->Level - inst->Min ;
  225.             inst->RedrawAll = TRUE ;
  226.             RollSize(inst, (Gadget *)object) ;
  227.             retval = (ULONG)object ;
  228.         }
  229.         break ;
  230.     case OM_DISPOSE:
  231.         retval = DoSuperMethodA(cl, o, msg) ;
  232.         break ;
  233.     case GM_HITTEST:
  234.         retval = DoSuperMethodA(cl, o, msg) ;
  235.         break ;
  236.     case GM_GOACTIVE:
  237.         {
  238.         gpInput *gpi = (gpInput *)msg ;
  239.         double   alpha, xp, yp, diff ;
  240.  
  241.             inst = (RollINST *)INST_DATA(cl, o) ;
  242.             if (gpi->gpi_IEvent) {
  243.                 ((Gadget *)o)->Flags |= GFLG_SELECTED ;
  244.                 inst->RedrawAll = FALSE ;
  245.  
  246.                 xp = double(gpi->gpi_Mouse.X - inst->XRadius) ;
  247.                 yp = double(inst->YRadius - gpi->gpi_Mouse.Y) * inst->Ratio ;
  248.  
  249.                 if (!xp) {
  250.                     alpha = cPID2 ;
  251.                     if (yp < 0)
  252.                         alpha = -alpha ;  // -PI/2 out of lims
  253.                 }
  254.                 else
  255.                     alpha = atan2(yp, xp) ;
  256.  
  257.                 alpha += cPID4 ;
  258.                 if (alpha < 0) alpha += c2PI ;
  259.                 diff = fabs(alpha -c2PI) ;
  260.                 if (diff < 0.00001) alpha = 0 ;
  261.  
  262.                 if (alpha <= inst->angMin)
  263.                     inst->Top =  long((inst->Total * (inst->angWidth - alpha))
  264.                         / inst->angWidth) ;
  265.  
  266.                 retval = GMR_MEACTIVE ;
  267.                 RenderERoll(cl, (Gadget *)o, (gpRender *)msg) ;
  268.                 *(gpi->gpi_Termination) = inst->Level ;
  269.                 NotifyRoll(cl, o, OPUF_INTERIM, inst->Level, gpi) ;
  270.         }
  271.         else
  272.             retval = GMR_NOREUSE ;
  273.         }
  274.         break ;
  275.     case GM_RENDER:
  276.         retval = RenderERoll(cl, (Gadget *)o, (gpRender *)msg) ;
  277.         break ;
  278.     case GM_HANDLEINPUT:
  279.         {
  280.             gpInput *gpi = (gpInput *)msg ;
  281.             InputEvent *ie = gpi->gpi_IEvent ;
  282.  
  283.             inst = (RollINST *)INST_DATA(cl, o) ;
  284.             inst->PTop = inst->Top ;
  285.             inst->RedrawAll = FALSE ;
  286.             retval = GMR_MEACTIVE ;
  287.  
  288.             if (ie->ie_Class == IECLASS_RAWMOUSE) {
  289.                 switch (ie->ie_Code) {
  290.                     case SELECTUP:
  291.                         *(gpi->gpi_Termination) = inst->Level ;
  292.                         retval = GMR_NOREUSE | GMR_VERIFY ;
  293.                         NotifyRoll(cl, o, 0, inst->Level, (gpInput *)msg) ;
  294.                         break ;
  295.                     case MENUDOWN:
  296.                         retval = GMR_REUSE ;
  297.                         NotifyRoll(cl, o, 0, inst->Level, (gpInput *)msg) ;
  298.                         break ;
  299.                     case IECODE_NOBUTTON:
  300.                         *(gpi->gpi_Termination) = inst->Level ;
  301.                         ie->ie_Code = inst->Level ;
  302.                         retval = GMR_MEACTIVE  ;
  303.                         NotifyRoll(cl, o, OPUF_INTERIM, inst->Level, gpi) ;
  304.                         break ;
  305.                 }
  306.             }
  307.             else if (ie->ie_Class == IECLASS_TIMER) {
  308.             double   alpha, xp, yp, diff ;
  309.                 xp = double(gpi->gpi_Mouse.X - inst->XRadius) ;
  310.                 yp = double(inst->YRadius - gpi->gpi_Mouse.Y) * inst->Ratio ;
  311.  
  312.                 if (!xp) {
  313.                     alpha = cPID2 ;
  314.                     if (yp < 0)
  315.                         alpha = - alpha ;
  316.                 }
  317.                 else
  318.                     alpha = atan2(yp, xp) ;
  319.  
  320.  
  321.                 alpha += cPID4 ;
  322.                 if (alpha < 0) alpha += c2PI ;
  323.                 diff = fabs(alpha -c2PI) ;
  324.                 if (diff < 0.00001) alpha = 0 ;
  325.  
  326.                 if (alpha <= inst->angMin)
  327.                     inst->Top =  long((inst->Total * (inst->angWidth - alpha))
  328.                         / inst->angWidth) ;
  329.  
  330.                 if (inst->PTop != inst->Top) {
  331.                     RenderERoll(cl, (Gadget *)o, (gpRender *)msg) ;
  332.                     NotifyRoll(cl, o, OPUF_INTERIM, inst->Level, gpi) ;
  333.                 }
  334.             }
  335.         }
  336.         break ;
  337.     case GM_GOINACTIVE:
  338.         ((Gadget *)o)-> Flags &= ~GFLG_SELECTED ;
  339.         inst = (RollINST *)INST_DATA(cl, o) ;
  340.         inst->KnobHit = FALSE ;
  341.         inst->RedrawAll = TRUE ;
  342.         RenderERoll(cl, (Gadget *)o, (gpRender *)msg) ;
  343.         break ;
  344.     case OM_GET:
  345.         {
  346.         ULONG *store = ((opGet *)msg)->opg_Storage ;
  347.  
  348.             inst = (RollINST *)INST_DATA(cl, o) ;
  349.             switch (((opGet *)msg)->opg_AttrID) {
  350.             case EGA_Min:
  351.                 *store = retval = inst->Min ;
  352.                 break ;
  353.             case EGA_Max:
  354.                 *store = retval = inst->Max ;
  355.                 break ;
  356.             case EGA_Level:
  357.                 *store = retval = inst->Level ;
  358.                 break ;
  359.             default:
  360.                 retval = DoSuperMethodA(cl, o, msg) ;
  361.             }
  362.         }
  363.         break ;
  364.     case OM_SET:
  365.         retval = DoSuperMethodA(cl, o, msg) ;
  366.         if ( FindTagItem(EGA_Min, ((opSet *)msg)->ops_AttrList) ||
  367.             FindTagItem(EGA_Max, ((opSet *)msg)->ops_AttrList) ||
  368.             FindTagItem(EGA_Level, ((opSet *)msg)->ops_AttrList) ) {
  369.             RastPort *rp ;
  370.             Gadget *g  = (Gadget *)o ;
  371.  
  372.             inst = (RollINST *)INST_DATA(cl, o) ;
  373.             inst->Min = (long)GetTagData(EGA_Min, inst->Min, ((opSet *)msg)->ops_AttrList) ;
  374.             inst->Max = (long)GetTagData(EGA_Max, inst->Max, ((opSet *)msg)->ops_AttrList) ;
  375.             inst->Level = (long)GetTagData(EGA_Level, inst->Level, ((opSet *)msg)->ops_AttrList) ;
  376.             inst->Total = inst->Max - inst->Min + 1 ;
  377.             inst->Top = inst->Level - inst->Min ;
  378.  
  379.  
  380.             if (rp = ObtainGIRPort( ((opSet *)msg)->ops_GInfo) ) {
  381.                 inst->RedrawAll = FALSE ;
  382.                 DoMethod(o, GM_RENDER, ((opSet *)msg)->ops_GInfo, rp, GREDRAW_REDRAW) ;
  383.                 ReleaseGIRPort(rp) ;
  384.                 inst->RedrawAll = TRUE ;
  385.             }
  386.         }
  387.         else
  388.             retval = DoSuperMethodA(cl, o, msg) ;
  389.         break ;
  390.     default :
  391.         retval = DoSuperMethodA(cl, o, msg) ;
  392.         break ;
  393.     }
  394.     return retval ;
  395. }
  396.  
  397.  
  398. void SAVEDS NotifyRoll(Class *cl, Object *o, ULONG flags, long level, gpInput *gpi)
  399. {
  400. static TagItem tt[3] ;
  401.  
  402.     GETA4 ;
  403.     tt[0].ti_Tag = EGA_Level ;
  404.     tt[0].ti_Data = level  ;
  405.  
  406.     tt[1].ti_Tag = GA_ID ;
  407.     tt[1].ti_Data = ((Gadget *)o)->GadgetID ;
  408.  
  409.     tt[2].ti_Tag = TAG_DONE ;
  410.  
  411.     DoSuperMethod(cl, o, OM_NOTIFY, tt, gpi->gpi_GInfo, flags) ;
  412. }
  413.  
  414. ULONG SAVEDS RenderERoll(Class *cl, Gadget *g, gpRender *msg)
  415. {
  416. RastPort    *rp ;
  417. ULONG       retval = TRUE ;
  418. UWORD       *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens ;
  419. RollINST    *inst = (RollINST *)INST_DATA(cl, (Object *)g) ;
  420. WORD        shine, shadow ;
  421.  
  422.     GETA4 ;
  423.     if (msg->MethodID == GM_RENDER)
  424.         rp = msg->gpr_RPort ;
  425.     else
  426.         rp = ObtainGIRPort(msg->gpr_GInfo) ;
  427.  
  428.     if (rp) {
  429.         shine = (g->Flags & GFLG_SELECTED)?pens[SHINEPEN]:pens[SHADOWPEN] ;
  430.         shadow = (g->Flags & GFLG_SELECTED)?pens[SHADOWPEN]:pens[SHINEPEN] ;
  431.         SetDrMd(rp, JAM1) ;
  432.  
  433.         if (g->Flags & GFLG_DISABLED) {
  434.             EraseRect(rp,
  435.                 inst->GLeft,
  436.                 inst->GTop,
  437.                 inst->GLeft+inst->GWidth,
  438.                 inst->GTop+inst->GHeight) ;
  439.         }
  440.         else {
  441.             if (!inst->RedrawAll) {
  442.                 EraseRect(rp, inst->KLeft-2, inst->KTop-2, inst->KRight+1, inst->KBottom+1) ;
  443.             }
  444.             RollLims(inst) ;
  445.             if (inst->RedrawAll) {
  446.                 EraseRect(rp,
  447.                     inst->GLeft,
  448.                     inst->GTop,
  449.                     inst->GLeft+inst->GWidth,
  450.                     inst->GTop+inst->GHeight) ;
  451.                 SetAPen(rp, pens[SHINEPEN]) ;
  452.                 DrawEllipse(rp, inst->CLeft, inst->CTop, inst->XRadius, inst->YRadius) ;
  453.                 SetAPen(rp, pens[SHADOWPEN]) ;
  454.                 DrawEllipse(rp, inst->CLeft-1, inst->CTop-1, inst->XRadius, inst->YRadius) ;
  455.             }
  456.             SetAPen(rp, shine) ;
  457.             DrawEllipse(rp, inst->KCenterX, inst->KCenterY, inst->XUnity, inst->YUnity) ;
  458.             SetAPen(rp, shadow) ;
  459.             DrawEllipse(rp, inst->KCenterX-1, inst->KCenterY-1, inst->XUnity, inst->YUnity) ;
  460.         }
  461.         if (msg->MethodID != GM_RENDER)
  462.             ReleaseGIRPort(rp) ;
  463.     }
  464.     else
  465.         retval = FALSE ;
  466.     return retval ;
  467. }
  468.  
  469. void SAVEDS RollSize(RollINST *inst, Gadget *g)
  470. {
  471. int     i ;
  472.  
  473.     GETA4 ;
  474.     inst->GLeft = g->LeftEdge ;
  475.     inst->GTop = g->TopEdge ;
  476.  
  477.     inst->CWidth = inst->GWidth = g->Width  ;
  478.     inst->CHeight = inst->GHeight = g->Height ;
  479.     inst->CWidth -= 2 ;
  480.     inst->CHeight -= 2 ;
  481.  
  482.     inst->XRadius = inst->CWidth/2 ;
  483.     inst->YRadius = inst->CHeight/2 ;
  484.     inst->Ratio = g->Width / g->Height ;
  485.  
  486.     inst->CLeft = inst->GLeft + inst->XRadius ;
  487.     inst->CTop = inst->GTop + inst->YRadius ;
  488.  
  489.     if (inst->CWidth > inst->CHeight) {
  490.         inst->YUnity = 1 ;
  491.         inst->XUnity = inst->CWidth / inst->CHeight ;
  492.     }
  493.     else {
  494.         inst->XUnity = 1 ;
  495.         inst->YUnity = inst->CHeight / inst->CWidth ;
  496.     }
  497.     inst->angPhase = c5PID4 ;
  498.     inst->angMin = c3PID2 ;
  499.     if (inst->Full) {
  500.         inst->angWidth = c2PI ;
  501.     }
  502.     else {
  503.         inst->angWidth = c3PID2 ;
  504.     }
  505.  
  506.     RollLims(inst) ;
  507. }
  508.  
  509. void SAVEDS RollLims(RollINST *inst)
  510. {
  511.     GETA4 ;
  512.     if (inst->Top < 0)
  513.         inst->Top = 0 ;
  514.     else if (inst->Top >= inst->Total)
  515.         inst->Top = inst->Total - 1 ;
  516.     inst->Level = inst->Top + inst->Min ;
  517.  
  518.     if (inst->Total)
  519.         inst->KStart = inst->angPhase -
  520.             (inst->Top * inst->angWidth) / inst->Total ;
  521.     else
  522.         inst->KStart = inst->angPhase ;
  523.  
  524.     inst->KCenterX = inst->CLeft +
  525.         long( cos(inst->KStart) * (inst->XRadius - (inst->XUnity * 3.0)) + .5) ;
  526.  
  527.     inst->KCenterY = inst->CTop -
  528.         long( sin(inst->KStart) * (inst->YRadius - (inst->YUnity * 3.0)) + .5) ;
  529.  
  530.     inst->KLeft = inst->KCenterX - inst->XUnity + 1 ;
  531.     inst->KRight = inst->KCenterX + inst->XUnity - 1 ;
  532.     inst->KTop = inst->KCenterY - inst->YUnity + 1 ;
  533.     inst->KBottom = inst->KCenterY + inst->YUnity - 1 ;
  534. }
  535.  
  536.  
  537.  
  538.